#include "Kernel.h"
//#include <fcntl.h>
//#include <stdio.h>
#include <fstream>
#include <string>
#include <iostream>

using namespace std;

Kernel::Kernel()
{
mailer=new Mailer();
scheduler=new Scheduler(30,20,myShell,mailer);
}

Kernel::Kernel(Shell1* shell)
{
myShell=shell;
mailer=new Mailer();
scheduler=new Scheduler(30,20,myShell,mailer);
}

Kernel::~Kernel()
{
delete myShell;
delete scheduler;
delete mailer;
}

void Kernel::StartOS()
{
scheduler->ChoosePolicy(0);
scheduler->Start();
}

int Kernel::SendText(int fromNode, int toNode, char* text) {

//cout<< "inside sendtext in kernel\n";
Message* temp_m = new Message(1,fromNode,fromNode,toNode,text);
Send(fromNode,temp_m);

}


int Kernel::Send(int DestinationThreadID, Message* msg)
{
	
	if (scheduler->getStatus(DestinationThreadID) != -2) {
		mailer->insert(DestinationThreadID, msg);
		return 0;
	}
	else 
	{
	return -1;
	}

}
		
Message* Kernel::Receive(int RecieverID)
{

return mailer->getMailbox(RecieverID)->Extract();

}



int Kernel::numofmessages(int RecieverID)
{
//cout<< RecieverID <<endl;
return mailer->getMailbox(RecieverID)->getSize();

}

int Kernel::CrashNode(int NodeID)
{
	if (Deadlock(NodeID)) {
	cout<< "Cannot crash node " << NodeID << " at this point as it would cause a deadlock\n";
	}
	else {
		scheduler->CrashNode(NodeID);
	}
	
}

bool Kernel::Deadlock(int id) 
{

	return mailer->isDeadlocked(id) && scheduler->isNodeInserting(id);
}

int Kernel::ReviveNode(int NodeID)
{
	scheduler->ReviveNode(NodeID);
}
		
void Kernel::ShowTable(int NodeID)
{
char* text = "stam";
Message* msg=new Message(3,NodeID,NodeID,NodeID,text);
Send(NodeID,msg);
}
		
int Kernel::KillAll()
{
 scheduler->KillAll();
 scheduler->ChoosePolicy(0);
}
		
double Kernel::Time()
{
return scheduler->getTime();
}
		
double Kernel::Time(int NodeID)
{
return scheduler->getTimeNodeI(NodeID);
}
		
int Kernel::Max_Length()
{
return mailer->getMaxLength();
}
		
int Kernel::Max_Length(int NodeID)
{
scheduler->getMaxLengthI(NodeID);
}
		
int Kernel::CreateNet(char* Filename)
{
			ID=0; //this is an ID
			string line;	
			int policy;
			int mailboxSize;
			int numOfNodes;
			ifstream myfile(Filename);
			if (myfile.is_open())
			{
				getline(myfile,line);
				policy = atoi(line.c_str()); 
				getline (myfile,line);
				mailboxSize = atoi(line.c_str());
				getline (myfile,line);
				numOfNodes = atoi(line.c_str());
				//cout << "the mailbox buffer size is " << mailboxSize << endl;
				//cout << "the number of nodes in the network is " << numOfNodes << endl;
				scheduler->setNodesCount(numOfNodes);
				myShell->setMailBoxSize(mailboxSize);
				nodes_mailboxes[-1]=myShell->getMailBox();
				char network[numOfNodes][numOfNodes];
				int place = 0;
				while (! myfile.eof() )
				{
					getline (myfile,line);
					for (i=0 ; i<numOfNodes; i++)
						network[place][i]=line[i*2];
					place++;
				}
				int neighbours[numOfNodes];
				//Node* temp;
				for (i=0 ; i<numOfNodes; i++) {
				//cout << "the neighbours of node "<< i<< " are: ";
					for (int j=0 ; j<numOfNodes ; j++){
						//cout << network[i][j];
						neighbours[j]=network[i][j]-'0';						
						}
						//cout<<"\n";
				//new Node(i,mailboxSize,numOfNodes,neighbours);
				//printf("hereeeeeeeeeeeee\n");
				nodes[i]=new Node(i,mailboxSize,numOfNodes,neighbours);
				//printf("hereeeeeeeeeeeee2\n");
				nodes_mailboxes[i]=nodes[i]->getMailBox();
				}
			//	printf("node size is: %d\n",nodes->size());
				mailer->emptyMailBox();
				mailer->setNodesMailBoxes(nodes_mailboxes,numOfNodes);
				scheduler->setNodeThreads(nodes);
				scheduler->Create();
				//cout<< "\n";
				if (policy==1){ //cout << "the scheduling policy is round robin" << endl;
				scheduler->ChoosePolicy(1);}
				if (policy==2){ //cout << "the scheduling policy is longest queue" << endl;
				scheduler->ChoosePolicy(2);}
				if (policy==3){ //cout << "the scheduling policy is our Special Policy" << endl;
				scheduler->ChoosePolicy(3);}
			myfile.close();
			return 0;	
			}
			else 
			{
			cout << "Unable to open file \n";
			return -1;
			} 
}







